// INCLUDES --------------------------------------------------------------------------------------------------
#include "wallclock.h"

// DEFINES ---------------------------------------------------------------------------------------------------
#define TIME_STOPWATCH_MAX 1000 // max amount of possible stopwatches

// PLATFORM-SPECIFIC PARTS -----------------------------------------------------------------------------------

// Windows
#ifdef WIN32
  #include <windows.h>

  // return elapsed milliseconds
  ui64 timeMs() { return (ui64)timeGetTime(); }
#endif // WIN32

// MacOSX, Linux
#ifdef UNIX
  #include <sys/time.h>

  // timeval structure contains seconds+microseconds
  static struct timeval t;

  // return elapsed milliseconds
  ui64 timeMs()
  {
    memset(&t, 0, sizeof(timeval));                      // clear structure
    gettimeofday(&t, NULL);                              // retrieve current time
    return (ui64)(t.tv_sec * 1000 + (t.tv_usec / 1000)); // return elapsed amount of (s+ms)
  }
#endif // UNIX

// FUNCTIONS -------------------------------------------------------------------------------------------------

// stopwatch function for measuring time intervals in milliseconds
static ui64 stopwatch[TIME_STOPWATCH_MAX];       // array of millisecond start times
static bool stopwatchInit = false;               // "array has been cleared once"

// clear stopwatch array values to zero once
static void stopwatchClear()
{
  /* if this is the first time we use the stopwatch functions,
     clear the stopwatch array */
  if (stopwatchInit == false)
  {
    memset(&stopwatch[0], 0, sizeof(stopwatch)); // clear array range
    stopwatchInit = true;                        // mark as "cleared"
  }
};

// START watch X, resetting marked time
void timeStopwatchStart(ui32 watch)
{
  stopwatchClear();                          // clear stopwatch arry
  ClampUi32(&watch, 0, TIME_STOPWATCH_MAX);  // clamp array range

  stopwatch[watch] = timeMs();               // save current ms-time in stopwatch X
};

// STOP watch X, return elapsed millisecond difference
ui64 timeStopwatchStop(ui32 watch)
{
  stopwatchClear();                          // clear stopwatch arry
  ClampUi32(&watch, 0, TIME_STOPWATCH_MAX);  // clamp array range

  if (stopwatch[watch] == 0) return 0;       // return zero, if this stopwatch hasn't been started yet!

  ui64 result = timeMs() - stopwatch[watch]; // calculate ms-time difference of watch X
  stopwatch[watch] = 0;                      // reset stopwatch X back to 0

  return result;                             // return ms-time difference of stopwatch X
};
